/*
#####################################################################
####################	   T R I B U I T 		#####################
#####################################################################

Copyright (C) 2010  Christoph Schnack, Berlin (Germany)

This file is part of Tribuit.

    Tribuit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Tribuit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tribuit.  If not, see <http://www.gnu.org/licenses/>.


########################################################################
*/
package Translate;

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

import javax.swing.*;

import GuiTools.*;
import Settings.*;
import Storage.*;

public class Translate {
	Language LANG;
	Storage MAINVOC;
	TribuitFrame transFrame;
	boolean crawlMeta,considerCase,considerPreFix;
	Comparison comp;
	String pattern;
	int patternLength;
	
	public void setIncludePreArg(boolean includePreFixArg){
		considerPreFix = includePreFixArg;
	}
	public void setConsCase(boolean consCase){
		considerCase=consCase;
	}
	public void setCrawlMetas(boolean crawlMetas){
		crawlMeta=crawlMetas;
	}
	
	public boolean getIncludePreArg(){
		return considerPreFix;
	}
	public boolean getConsCase(){
		return considerCase;
	}
	public boolean getCrawlMetas(){
		return crawlMeta;
	}
	public void setLanguage(Language lan){
		LANG=lan;
	}
	public void setStorage(Storage st){
		MAINVOC=st;
	}
	
	
	public Translate(String txt, String opt, String voc){
		//LANG=lan;
		//MAINVOC=st;
		//crawlMeta=crawlMetas;
		//considerCase=consCase;
		//considerPreFix = includePreFixArg;
		transFrame = new TribuitFrame(LANG.getLookup());
		comp = new StartsWith();
		if(opt.equals("endsWith")) comp = new EndsWith();
		if(opt.equals("containsString")) comp = new Contains();
		if(opt.equals("containsChars")) comp = new ContainsChars();
		if(opt.equals("exactMatch"))comp = new ExactMatch();
		if(opt.equals("anagrams"))comp = new Anagram();
		if(opt.equals("resembles"))comp = new Resemble();
		Vocabulary[] vocs;
		if(voc.equals(LANG.getAll()))vocs = MAINVOC.getVocabulariesWithWords();
		else vocs = new Vocabulary[] {MAINVOC.getVocabulary(voc)};
		JTabbedPane vocPane = new JTabbedPane();
		pattern=txt.trim();
		if(!considerCase) pattern=pattern.toLowerCase();
		patternLength = pattern.length();
		int hits=0;
		Vector<String> hitNamesA,hitNamesB;
		for(Vocabulary v : vocs){
			hitNamesA = new Vector<String>();
			hitNamesB = new Vector<String>();
			JTabbedPane vocAJTB=new JTabbedPane(),vocBJTB=new JTabbedPane();
			vocAJTB.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
			vocBJTB.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
			Word[] words = v.getWords();
			boolean hitA=false,hitB=false,matchA,matchB;
			int foundA=0,foundB=0;
			for(Word w : words){
				matchA = false;
				matchB = false;
				for(Meaning m :w.getMeaningVectorA()){
					if(!hitNamesA.contains(w.getName()) && ((considerPreFix)?(comp.compare(m.getMeaningWithArticleUnformatted())||comp.compare(m.getMeaning())):comp.compare(m.getMeaning())) ){
						hitNamesA.add(w.getName());
						vocAJTB.addTab(""+(++foundA),entry(w,foundA,false,v));
						hitA=true;
						matchA=true;
						hits++;
						break;
					}
					if(m.hasSynonyms()){
						for(Term t : m.getSynonyms()){
							if(!hitNamesA.contains(w.getName()) && ((considerPreFix)?(comp.compare(t.getTermWithArticleUnformatted())||comp.compare(t.getTerm())):comp.compare(t.getTerm())) ){
								hitNamesA.add(w.getName());
								vocAJTB.addTab(""+(++foundA),entry(w,foundA,false,v));
								hitA=true;
								matchA=true;
								hits++;
								break;
							}
						}
					}
					if(getCrawlMetas() && !matchA){
						if(m.hasMeta()){
							String tmpWrd;
							for(String s : m.getMetaDescription().keySet().toArray(new String[m.getMetaDescription().keySet().size()])){
								tmpWrd = m.getMetaElement(s);
								if(tmpWrd!=null && !tmpWrd.equals("")){
									if(!hitNamesA.contains(w.getName()) && comp.compare( tmpWrd)){
										hitNamesA.add(w.getName());
										vocAJTB.addTab(""+(++foundA),entry(w,foundA,false,v));
										hitA=true;
										matchA=true;
										hits++;
										break;
									}
								}
							}
						}
					}
				}
				for(Meaning m : w.getMeaningVectorB()){
					if(!hitNamesB.contains(w.getName()) && ((considerPreFix)?(comp.compare(m.getMeaningWithArticleUnformatted())||comp.compare(m.getMeaning())):comp.compare(m.getMeaning())) ){
						hitNamesB.add(w.getName());
						vocBJTB.addTab(""+(++foundB),entry(w,foundB,true,v));
						hitB=true;
						matchB=true;
						hits++;
						break;
					}
					if(m.hasSynonyms()){
						for(Term t : m.getSynonyms()){
							if(!hitNamesB.contains(w.getName()) && ((considerPreFix)?(comp.compare(t.getTermWithArticleUnformatted())||comp.compare(t.getTerm())):comp.compare(t.getTerm())) ){
								hitNamesB.add(w.getName());
								vocBJTB.addTab(""+(++foundB),entry(w,foundB,true,v));
								hitB=true;
								matchB=true;
								hits++;
								break;
							}
						}
					}
				}
				if(getCrawlMetas() && !matchB){
					for(Meaning m : w.getMeaningVectorB()){
						if(m.hasMeta()){
							String tmpWrd;
							for(String s : m.getMetaDescription().keySet().toArray(new String[m.getMetaDescription().keySet().size()])){
								tmpWrd = m.getMetaElement(s);
								if(tmpWrd!=null && !tmpWrd.equals("")){
									if(!hitNamesB.contains(w.getName()) && comp.compare( tmpWrd)){
										hitNamesB.add(w.getName());
										vocBJTB.addTab(""+(++foundB),entry(w,foundB,true,v));
										hitB=true;
										matchB=true;
										hits++;
										break;
									}
								}
							}
						}
					}
				}
			}
			if(hitA){
				vocPane.addTab(v.getName()+" ("+foundA+")",vocAJTB);
				SwingUtilities.invokeLater(new Runnable(){
					public void run() {
						//Ajsp.getViewport().setViewPosition(new Point(0, 0));
					}
				});
			}
			if(hitB){
				vocPane.addTab(v.getNameB()+" - "+v.getNameA()+" ("+foundB+")",vocBJTB);
				SwingUtilities.invokeLater(new Runnable(){
					public void run() {
						//Bjsp.getViewport().setViewPosition(new Point(0, 0));
					}
				});
			}
		}
		vocPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		JPanel resultPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JLabel resultLabel = new JLabel(hits+" "+((hits==1)? LANG.getResultFor():LANG.getResultsFor())+": ");
		resultLabel.setFont(new Font(Font.SERIF,Font.BOLD,17));
		JLabel resultLabelTxt = new JLabel(pattern);
		resultLabelTxt.setFont(new Font(Font.SERIF,Font.PLAIN,17));
		resultPanel.add(resultLabel);
		resultPanel.add(resultLabelTxt);

		JLabel metaText = new JLabel((crawlMeta)? LANG.getYes():LANG.getNo()+"   ");
		metaText.setFont(new Font(Font.SERIF,Font.ITALIC,14));
		JLabel speciesText = new JLabel(opt);
		speciesText.setFont(new Font(Font.SERIF,Font.ITALIC,14));
		JLabel articleText = new JLabel((considerPreFix?LANG.getYes():LANG.getNo()));
		articleText.setFont(new Font(Font.SERIF,Font.ITALIC,14));
		
		JPanel optPanel = new JPanel(new GridLayout(3,3));
		optPanel.add(new JLabel(LANG.getCrawlMetas()+": "));
		optPanel.add(metaText);
		optPanel.add(new JLabel(LANG.getConsiderPreFix()+": "));
		optPanel.add(articleText);
		optPanel.add(new JLabel(LANG.getPatternSpecies()+": "));
		optPanel.add(speciesText);
		
		JPanel center = new JPanel();
		center.setLayout(new GridBagLayout());
		GridBagConstraints cGBC = new GridBagConstraints();
		cGBC.insets = new Insets(0,5,0,5);
		cGBC.anchor=GridBagConstraints.NORTHWEST;
		cGBC.fill=GridBagConstraints.NONE;
		cGBC.gridy=0;
		center.add(resultPanel,cGBC);
		cGBC.gridy=1;
		center.add(optPanel,cGBC);
		cGBC.fill=GridBagConstraints.BOTH;
		cGBC.gridy=2;
		cGBC.weightx = 1;
		cGBC.weighty = 1;
		center.add(vocPane,cGBC);
		JButton closeBtn = new JButton(LANG.getClose());
		closeBtn.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				transFrame.dispose();
			}
		});
		JPanel closeBtnPanel = new JPanel();
		closeBtnPanel.add(closeBtn);
		transFrame.getContentPane().add(BorderLayout.NORTH,new Header(LANG.getLookup()));
		transFrame.getContentPane().add(BorderLayout.CENTER,center);
		transFrame.getContentPane().add(BorderLayout.SOUTH,closeBtnPanel);
		transFrame.setResizable(true);
		transFrame.showUp(100,100);
		closeBtn.requestFocus();
	}
	
	public JScrollPane entry(Word wrd,int matchNr,boolean inv,Vocabulary foundInVoc){
		JPanel panel = new JPanel();
		panel.setLayout(new GridBagLayout());
		
	//TERM A
		JPanel panelA = new JPanel();
		panelA.setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();;
		int num=1;
		JLabel tcLabel = new JLabel(wrd.getTermclassA());
		tcLabel.setFont(new Font(Font.SERIF,Font.ITALIC,14));
		gbc.anchor = GridBagConstraints.NORTH;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = GridBagConstraints.REMAINDER;
		gbc.weighty = 0;
		gbc.weightx = 1;
		panelA.add(tcLabel,gbc);
		gbc.insets = new Insets(5,0,0,0);
		for(Meaning m : wrd.getMeaningVectorA()){
			panelA.add(new MeaningPanel(transFrame,m,num++,LANG,foundInVoc.getTermclassA(wrd.getTermclassA()).getSortedKeys()),gbc);
		}
		gbc.weighty = 1;
		panelA.add(new JPanel(),gbc);

	//Term B
		gbc.weighty = 0;
		num=1;
		JPanel panelB = new JPanel();
		panelB.setLayout(new GridBagLayout());
		JLabel tcbLabel = new JLabel(wrd.getTermclassB());
		tcbLabel.setFont(new Font(Font.SERIF,Font.ITALIC,14));
		gbc.insets = new Insets(0,0,0,0);
		panelB.add(tcbLabel,gbc);
		gbc.insets = new Insets(5,0,0,0);
		for(Meaning m : wrd.getMeaningVectorB()){
			panelB.add(new MeaningPanel(transFrame, m,num++,LANG,foundInVoc.getTermclassB(wrd.getTermclassB()).getSortedKeys()),gbc);
		}
		gbc.weighty = 1;
		panelB.add(new JPanel(),gbc);

		JLabel dash = new JLabel("-");
		dash.setFont(new Font(Font.SERIF,Font.BOLD,16));
		
		JLabel sectionLabel = new JLabel(LANG.getSection()+ ": ");
		sectionLabel.setFont(new Font(Font.SERIF,Font.BOLD,15));
		JLabel section = new JLabel(wrd.getLection());
		section.setFont(new Font(Font.SERIF,Font.PLAIN,15));
		JPanel sectionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		sectionPanel.add(sectionLabel);
		sectionPanel.add(section);
		
		gbc  = new GridBagConstraints();
		gbc.fill = GridBagConstraints.BOTH;
		gbc.anchor=GridBagConstraints.NORTHWEST;
		gbc.insets = new Insets(0,0,5,0);
		gbc.gridy=0;
		gbc.gridx=0;
		panel.add(sectionPanel,gbc);
		
		gbc.gridy = 1;
		gbc.weighty=1;
		gbc.weightx=1;
		panel.add((inv)?panelB:panelA,gbc);
		
		gbc.gridx=1;
		gbc.insets = new Insets(0,20,0,20);
		gbc.weightx=0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		panel.add(dash,gbc);
		
		gbc.gridx=2;
		gbc.weightx=1;
		//gbc.weighty=1;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.insets = new Insets(0,0,5,0);
		panel.add((inv)?panelA:panelB,gbc);
		return new CustomScrollPane(panel);
	}
	
	abstract class Comparison{
		abstract public boolean compare(String st);
	}
	
	class StartsWith extends Comparison{
		public boolean compare(String object){
			object=object.trim();
			if(considerCase){
				return pattern.equals((object.length()<pattern.length())?object:object.substring(0,patternLength));
			}
			else return object.toLowerCase().startsWith(pattern);
		}
	}
	
	class EndsWith extends Comparison{
		public boolean compare(String object){
			object=object.trim();
			if(considerCase){
				return pattern.equals((object.length()<patternLength)?object:object.substring(object.length()-patternLength));
			}
			else return object.toLowerCase().endsWith(pattern);
		}
	}
	
	class ExactMatch extends Comparison{
		public boolean compare(String object){
			object=object.trim();
			if(!considerCase)object = object.toLowerCase();
			return object.equals(pattern);
		}
	}
	
	class Contains extends Comparison{
		public boolean compare(String object){
			object=object.trim();
			if(!considerCase) object = object.toLowerCase();
			return object.contains(pattern);
		}
	}
	
	class ContainsChars extends Comparison{
		public boolean compare(String object){
			object=object.trim();
			if(!considerCase)object = object.toLowerCase();
			char[] chars = pattern.toCharArray();
			for(char c : chars){
				if(!object.contains(""+c)) return false;
				else object=object.replaceFirst(c+"","");
			}
			return true;
		}
	}
	
	class Anagram extends Comparison{
		public boolean compare(String object){
			object=object.trim();
			if(!considerCase)object = object.toLowerCase();
			char[] chars = pattern.toCharArray();
			for(char c : chars){
				if(!object.contains(""+c)) return false;
				else object=object.replaceFirst(c+"","");
			}
			return object.length()==0;
		}
	}

	class Resemble extends Comparison{
		int difference = 2;
		public boolean compare(String dataBaseEntry){
			dataBaseEntry=dataBaseEntry.trim();
			if(dataBaseEntry.length()-pattern.length()<-1 || dataBaseEntry.length()-pattern.length()>1) return false;
			if(!considerCase)dataBaseEntry = dataBaseEntry.toLowerCase();
			if(dataBaseEntry.contains(pattern) || pattern.contains(dataBaseEntry)) return true;
			return (dropLetters(difference,dataBaseEntry,pattern,false) || dropLetters(difference,pattern,dataBaseEntry,false));
		}
		
		private boolean dropLetters(int count,String pattern, String toDrop, boolean switched){
			String cut;
			char[] oChars = toDrop.toCharArray();
			for(int i=0;i<oChars.length;i++){
				cut="";
				for(int r=0;r<oChars.length;r++){
					if(r!=i)cut+=oChars[r];
				}
				if(pattern.equals(cut))return true;
				else{
					if(count>1 && oChars.length>2 && dropLetters(count-1,pattern,cut,false))return true;
					if(!switched&&count>1&&pattern.length()>1 && dropLetters(count,cut, pattern,true)) return true;
				}
			}
			return false;
		}
	}
}
